home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / operation.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  22KB  |  806 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <X11/Xaw/Form.h>
  18. #include <X11/Xaw/SmeBSB.h>
  19. #include <X11/Xaw/Box.h>
  20. #include <X11/Xaw/Toggle.h>
  21. #include <X11/Xaw/Viewport.h>
  22. #include <X11/cursorfont.h>
  23. #include <stdio.h>
  24.  
  25. #ifndef NOSTDHDRS
  26. #include <stdlib.h>
  27. #include <unistd.h>
  28. #endif
  29.  
  30. #include "image.h"
  31.  
  32. #include "bitmaps/brushOp.xbm"
  33. #include "bitmaps/brushOp.xpm"
  34. #include "bitmaps/eraseOp.xbm"
  35. #include "bitmaps/sprayOp.xbm"
  36. #include "bitmaps/sprayOp.xpm"
  37. #include "bitmaps/pencilOp.xbm"
  38. #include "bitmaps/pencilOp.xpm"
  39. #include "bitmaps/dotPenOp.xbm"
  40. #include "bitmaps/dotPenOp.xpm"
  41. #include "bitmaps/lineOp.xbm"
  42. #include "bitmaps/arcOp.xbm"
  43. #include "bitmaps/fillOp.xbm"
  44. #include "bitmaps/fillOp.xpm"
  45. #include "bitmaps/textOp.xbm"
  46. #include "bitmaps/selectOp.xbm"
  47. #include "bitmaps/boxOp.xbm"
  48. #include "bitmaps/rayOp.xbm"
  49. #include "bitmaps/fboxOp.xbm"
  50. #include "bitmaps/ovalOp.xbm"
  51. #include "bitmaps/fovalOp.xbm"
  52. #include "bitmaps/lassoOp.xbm"
  53. #include "bitmaps/clineOp.xbm"
  54. #include "bitmaps/polyOp.xbm"
  55. #include "bitmaps/fpolyOp.xbm"
  56. #include "bitmaps/blobOp.xbm"
  57. #include "bitmaps/fblobOp.xbm"
  58. #include "bitmaps/selareaOp.xbm"
  59.  
  60. #include <xpm.h>
  61.  
  62. extern void AboutDialog(Widget);
  63.  
  64. #define    OP_BEGIN    0
  65. #define    OP_END        1
  66.  
  67. #include "xpaint.h"
  68. #include "misc.h"
  69. #include "menu.h"
  70. #include "Paint.h"
  71. #include "text.h"
  72. #include "ops.h"
  73. static void changeLineAction(Widget, XEvent *);
  74. static void changeSprayAction(Widget, XEvent *);
  75. static void changeBrushAction(Widget, XEvent *);
  76. static void changeChromaAction(Widget, XEvent *);
  77. static void changeFontAction(Widget, XEvent *);
  78.  
  79. static void setOperation(Widget w, XtPointer opArg, XtPointer junk2) 
  80. {
  81.     Operation_t    *op = (Operation_t*)opArg;
  82.     Operation_t    stop, start;
  83.  
  84.     if (op == CurrentOp)
  85.         return;
  86.  
  87.     stop  = CurrentOp ? CurrentOp[OP_END]   : NULL;
  88.     start = op        ? op       [OP_BEGIN] : NULL;
  89.  
  90.     GraphicSetOp((OperationRemoveProc)stop, (OperationAddProc)start);
  91.  
  92.     CurrentOp = op;
  93. }
  94.  
  95. /*
  96. **  The set line width callback pair
  97. */
  98. static char    currentLineWidth[10] = "1";
  99.  
  100. static void setWidth(Widget w, void *width)
  101. {
  102.     XtVaSetValues(w, XtNlineWidth, (int)width, NULL);
  103. }
  104. static void okLineCallback(Widget w, XtPointer junk, XtPointer infoArg)
  105. {
  106.     Arg        arg;
  107.     TextPromptInfo    *info = (TextPromptInfo*)infoArg;
  108.     int        width = atoi(info->prompts[0].rstr);
  109.  
  110.     if (width < 1 || width > 1000) {
  111.         Notice(w, "Invalid width, must be greater than zero and less than 1000");
  112.         return;
  113.     }
  114.     sprintf(currentLineWidth, "%d", width);
  115.  
  116.     MenuCheckItem(w, True);
  117.  
  118.     if (width == 1)
  119.         width = 0;
  120.     GraphicAll(setWidth, (void*)width);
  121.     XtSetArg(arg, XtNlineWidth, width);
  122.     OperationAddArg(arg);
  123. }
  124. static void lineWidth(Widget w, int width)
  125. {
  126.     String    lbl;
  127.  
  128.     XtVaGetValues(w, XtNlabel, &lbl, NULL);
  129.     width = atoi(lbl);
  130.     if (width <= 0) {
  131.         static TextPromptInfo        info;
  132.         static struct textPromptInfo    value[1];
  133.  
  134.         value[0].prompt = "Width:";
  135.         value[0].str    = currentLineWidth;
  136.         value[0].len    = 4;
  137.         info.prompts = value;
  138.         info.title   = "Enter desired line width";
  139.         info.nprompt = 1;
  140.  
  141.         TextPrompt(w, "linewidth", &info, okLineCallback, NULL, NULL);
  142.     } else {
  143.         Arg    arg;
  144.  
  145.         if (width == 1)
  146.             width = 0;
  147.         MenuCheckItem(w, True);
  148.         GraphicAll(setWidth, (void *)width);
  149.  
  150.         XtSetArg(arg, XtNlineWidth, width);
  151.         OperationAddArg(arg);
  152.     }
  153. }
  154. /*
  155. **
  156. */
  157. static char    sprayDensityStr[10] = "10";
  158. static char    sprayRadiusStr[10] = "10";
  159. static char    sprayRateStr[10] = "10";
  160. static void sprayOkCallback(Widget w, XtPointer junk, XtPointer infoArg)
  161. {
  162.     void        SpraySetParameters(int, int, int);
  163.     TextPromptInfo    *info = (TextPromptInfo*)infoArg;
  164.     int        radius  = atoi(info->prompts[0].rstr);
  165.     int        density = atoi(info->prompts[1].rstr);
  166.     int        rate    = atoi(info->prompts[2].rstr);
  167.  
  168.     if (radius < 1 || radius > 100) {
  169.         Notice(w, "Radius should be between 1 and 100");
  170.         return;
  171.     }
  172.     if (density < 1 || density > 500) {
  173.         Notice(w, "Density should be between 1 and 500");
  174.         return;
  175.     }
  176.     if (rate < 1 || rate > 500) {
  177.         Notice(w, "Rate should be between 1 and 500");
  178.         return;
  179.     }
  180.  
  181.     SpraySetParameters(radius, density, rate);
  182.  
  183.     sprintf(sprayDensityStr,"%d",density);
  184.     sprintf(sprayRadiusStr,"%d",radius);
  185.     sprintf(sprayRateStr,"%d",rate);
  186. }
  187. static void sprayMenuCallback(Widget w)
  188. {
  189.     static TextPromptInfo        info;
  190.     static struct textPromptInfo    value[3];
  191.  
  192.     value[0].prompt = "Radius:";
  193.     value[0].str    = sprayRadiusStr;
  194.     value[0].len    = 4;
  195.     value[1].prompt = "Density:";
  196.     value[1].str    = sprayDensityStr;
  197.     value[1].len    = 4;
  198.     value[2].prompt = "Rate:";
  199.     value[2].str    = sprayRateStr;
  200.     value[2].len    = 4;
  201.     info.prompts = value;
  202.     info.title   = "Enter the desired spray parameters";
  203.     info.nprompt = 3;
  204.  
  205.     TextPrompt(w, "sprayparams", &info, sprayOkCallback, NULL, NULL);
  206. }
  207.  
  208. /*
  209. **  Font menu callbacks.
  210. */
  211. static void fontSetCallback(Widget paint, void *info)
  212. {
  213.     XtVaSetValues(paint, XtNfont, (XFontStruct*)info, NULL);
  214.     FontChanged(paint);
  215. }
  216. static void fontSet(Widget w, char *name)
  217. {
  218.     XFontStruct    *info;
  219.     Arg        arg;
  220.  
  221.     if (name == NULL) {
  222.         FontSelect(w, None);
  223.     } else {
  224.         if ((info = XLoadQueryFont(XtDisplay(GetShell(w)), name)) == NULL) {
  225.             XtVaSetValues(w, XtNsensitive, False, NULL);
  226.             Notice(w, "Unable to load requested font");
  227.             return;
  228.         }
  229.         GraphicAll(fontSetCallback, (void*)info);
  230.         XtSetArg(arg, XtNfont, info);
  231.         OperationAddArg(arg);
  232.     }
  233.     MenuCheckItem(w, True);
  234. }
  235.  
  236. /*
  237. **  Exit callback (simple)
  238. */
  239. static void exitOkCallback(Widget w, XtPointer junk, XtPointer junk2)
  240. {
  241. #if 0
  242.     XtDestroyWidget(GetToplevel(w));
  243.     XtDestroyApplicationContext(XtWidgetToApplicationContext(w));
  244.     Global.timeToDie = True;
  245. #else
  246.     exit(0);
  247. #endif
  248. }
  249. static void exitCancelCallback(Widget paint, XtPointer junk, XtPointer junk2)
  250. {
  251. }
  252. static void exitPaintCheck(Widget paint, void *sumArg)
  253. {
  254.     int    *sum = (int *)sumArg;
  255.     Boolean    flg;
  256.     XtVaGetValues(paint, XtNdirty, &flg, NULL);
  257.     *sum += flg ? 1 : 0;
  258. }
  259. static void exitPaint(Widget w, XtPointer junk, XtPointer junk2)
  260. {
  261.     int    total = 0;
  262.  
  263.     GraphicAll(exitPaintCheck, (void*)&total);
  264.  
  265.     if (total == 0) {
  266.         exitOkCallback(w, NULL, NULL);
  267.         return;
  268.     }
  269.     
  270.     AlertBox(w, "There are unsaved changes,\nare you sure you wish to quit?",
  271.                 exitOkCallback, exitCancelCallback, NULL);
  272. }
  273.  
  274. /*
  275. **
  276. */
  277. extern void ClipboardSetImage(Widget, void *);
  278.  
  279. static void loadClipboardCB(Widget w, char *file, void *image)
  280. {
  281.     ClipboardSetImage(w, image);
  282. }
  283. static void loadClipboard(Widget w, XtPointer junk, XtPointer junk2)
  284. {
  285.     GetFileName(GetShell(w), 0, NULL, (XtCallbackProc)loadClipboardCB, NULL);        
  286. }
  287.  
  288.  
  289. /*
  290. **  Button popus 
  291. */
  292. static void    erasePopupCB(Widget w, XtPointer junk, XtPointer junk2);
  293. static void    fillPopupCB(Widget w, XtPointer junk, XtPointer junk2);
  294. static void    selectPopupCB(Widget w, XtPointer junk, XtPointer junk2);
  295. static void    sprayPopupCB(Widget w, XtPointer junk, XtPointer junk2);
  296. static void    ovalPopupCB(Widget w, XtPointer junk, XtPointer junk2);
  297. static void    boxPopupCB(Widget w, XtPointer junk, XtPointer junk2);
  298.  
  299. #define GENERATE_HELP(name, hlpstr)                \
  300.         static PaintMenuItem name [] = {        \
  301.             MI_SEPERATOR(),                \
  302.             MI_SIMPLECB("help", HelpDialog, hlpstr)    \
  303.         };
  304.  
  305. static PaintMenuItem brushPopup[] = {
  306.     MI_SEPERATOR(),
  307.     MI_SIMPLECB("select", BrushSelect, NULL),
  308.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.brush"),
  309. };
  310. static PaintMenuItem erasePopup[] = {
  311.     MI_SEPERATOR(),
  312.     MI_FLAGCB("original", MF_CHECKON, erasePopupCB, 0),
  313.     MI_SIMPLECB("select", changeBrushAction, NULL),
  314.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.erase"),
  315. };
  316. static PaintMenuItem sprayPopup[] = {
  317.     MI_SEPERATOR(),
  318.     MI_FLAGCB("gauss", MF_CHECKON, sprayPopupCB, 0),
  319.     MI_SIMPLECB("select", changeSprayAction, NULL),
  320.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.spray"),
  321. };
  322. GENERATE_HELP(pencilPopup, "toolbox.tools.pencil")
  323. GENERATE_HELP(dotPencilPopup, "toolbox.tools.dotPencil")
  324. GENERATE_HELP(linePopup, "toolbox.tools.line")
  325. GENERATE_HELP(rayPopup, "toolbox.tools.ray")
  326. GENERATE_HELP(arcPopup, "toolbox.tools.arc")
  327. static PaintMenuItem fillPopup[] = {
  328.     MI_SEPERATOR(),
  329.     MI_FLAGCB("fill", MF_CHECKON|MF_GROUP1, fillPopupCB, 0),
  330.     MI_FLAGCB("change", MF_CHECK|MF_GROUP1, fillPopupCB, 1),
  331.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.fill"),
  332. };
  333. static PaintMenuItem textPopup[] = {
  334.     MI_SEPERATOR(),
  335.     MI_SIMPLECB("select", changeFontAction, NULL),
  336.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.text"),
  337. };
  338. GENERATE_HELP(polyPopup, "toolbox.tools.poly")
  339. GENERATE_HELP(freehandPopup, "toolbox.tools.blob")
  340. GENERATE_HELP(clinePopup, "toolbox.tools.cline")
  341. static PaintMenuItem selectBPopup[] = {
  342.     MI_SEPERATOR(),
  343.     MI_FLAGCB("shape", MF_CHECKON|MF_GROUP1, selectPopupCB, 0),
  344.     MI_FLAGCB("not_color", MF_CHECK|MF_GROUP1, selectPopupCB, 1),
  345.     MI_FLAGCB("only_color", MF_CHECK|MF_GROUP1, selectPopupCB, 2),
  346.     MI_SIMPLECB("select", changeChromaAction, NULL),
  347.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.select"),
  348. };
  349. static PaintMenuItem selectAPopup[] = {
  350.     MI_SEPERATOR(),
  351.     MI_FLAGCB("shape", MF_CHECKON|MF_GROUP1, selectPopupCB, 0),
  352.     MI_FLAGCB("not_color", MF_CHECK|MF_GROUP1, selectPopupCB, 1),
  353.     MI_FLAGCB("only_color", MF_CHECK|MF_GROUP1, selectPopupCB, 2),
  354.     MI_SIMPLECB("select", changeChromaAction, NULL),
  355.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.select"),
  356. };
  357. static PaintMenuItem boxPopup[] = {
  358.     MI_SEPERATOR(),
  359.     MI_FLAGCB("center", MF_CHECK, boxPopupCB, 0),
  360.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.box"),
  361. };
  362. static PaintMenuItem fboxPopup[] = {
  363.     MI_SEPERATOR(),
  364.     MI_FLAGCB("center", MF_CHECK, boxPopupCB, 0),
  365.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.box"),
  366. };
  367. static PaintMenuItem ovalPopup[] = {
  368.     MI_SEPERATOR(),
  369.     MI_FLAGCB("center", MF_CHECK, ovalPopupCB, 0),
  370.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.oval"),
  371. };
  372. static PaintMenuItem fovalPopup[] = {
  373.     MI_SEPERATOR(),
  374.     MI_FLAGCB("center", MF_CHECK, ovalPopupCB, 0),
  375.     MI_SIMPLECB("help", HelpDialog, "toolbox.tools.oval"),
  376. };
  377. static void    ovalPopupCB(Widget w, XtPointer junk, XtPointer junk2)
  378. {
  379.     Boolean    m = !CircleGetStyle();
  380.  
  381.     CircleSetStyle(m);
  382.     MenuCheckItem(ovalPopup[1].widget, m);
  383.     MenuCheckItem(fovalPopup[1].widget, m);
  384. }
  385. static void    boxPopupCB(Widget w, XtPointer junk, XtPointer junk2)
  386. {
  387.     Boolean    m = !BoxGetStyle();
  388.  
  389.     BoxSetStyle(m);
  390.     MenuCheckItem(boxPopup[1].widget, m);
  391.     MenuCheckItem(fboxPopup[1].widget, m);
  392. }
  393. static void    fillPopupCB(Widget w, XtPointer junk, XtPointer junk2)
  394. {
  395.     int    nm = (int)junk;
  396.  
  397.     FillSetMode(nm);
  398.     MenuCheckItem(fillPopup[nm + 1].widget, True);
  399. }
  400. static void    selectPopupCB(Widget w, XtPointer junk, XtPointer junk2)
  401. {
  402.     int    n = (int)junk;
  403.  
  404.     MenuCheckItem(selectAPopup[n + 1].widget, True);
  405.     MenuCheckItem(selectBPopup[n + 1].widget, True);
  406.     SelectSetCutMode(n);
  407. }
  408. void OperationSelectCallAcross(int n)
  409. {
  410.     MenuCheckItem(selectAPopup[n + 1].widget, True);
  411.     MenuCheckItem(selectBPopup[n + 1].widget, True);
  412. }
  413. static void    sprayPopupCB(Widget w, XtPointer junk, XtPointer junk2)
  414. {
  415.     Boolean    m = !SprayGetStyle();
  416.  
  417.     SpraySetStyle(m);
  418.     MenuCheckItem(w, m);
  419. }
  420. static void    erasePopupCB(Widget w, XtPointer junk, XtPointer junk2)
  421. {
  422.     Boolean    m = !EraseGetMode();
  423.  
  424.     EraseSetMode(m);
  425.     MenuCheckItem(w, m);
  426. }
  427.  
  428. /*
  429. **  Done with operation popup menus
  430. */
  431.  
  432. #define GENERATE_OP(name)                \
  433.     extern void *CONCAT(name,Add)(Widget w,...),    \
  434.             *CONCAT(name,Remove)(Widget w,...);    \
  435.     static Operation_t  CONCAT(name,Op)[] = {    \
  436.         CONCAT(name,Add), CONCAT(name,Remove)    \
  437.     };
  438.  
  439. GENERATE_OP(DotPencil)
  440. GENERATE_OP(Pencil)
  441. GENERATE_OP(Box)
  442. GENERATE_OP(FBox)
  443. GENERATE_OP(Line)
  444. GENERATE_OP(Ray)
  445. GENERATE_OP(Arc)
  446. GENERATE_OP(Oval)
  447. GENERATE_OP(FOval)
  448. GENERATE_OP(Erase)
  449. GENERATE_OP(Brush)
  450. GENERATE_OP(Font)
  451. GENERATE_OP(Smear)
  452. GENERATE_OP(Spray)
  453. GENERATE_OP(Poly)
  454. GENERATE_OP(FPoly)
  455. GENERATE_OP(Freehand)
  456. GENERATE_OP(FFreehand)
  457. GENERATE_OP(CLine)
  458. GENERATE_OP(Fill)
  459. GENERATE_OP(SelectBox)
  460. GENERATE_OP(SelectArea)
  461. #if 0
  462. GENERATE_OP(SelectChroma)
  463. #endif
  464.  
  465. #define    BITMAP(name)    \
  466.     NULL, (char *)CONCAT(name,Op_bits) , CONCAT(name,Op_width), CONCAT(name,Op_height)
  467. #define    XPMMAP(name)    \
  468.     (char **)CONCAT(name,Op_xpm) , NULL , CONCAT(name,Op_width), CONCAT(name,Op_height)
  469. #define MENU(name)    XtNumber(CONCAT(name,Popup)), CONCAT(name,Popup)
  470.  
  471. typedef struct {
  472.     char        *name;
  473.     char        **xpmmap;
  474.     char        *bitmap;
  475.     int        width, height;
  476.     void        (*callback)();        /* By default setOperation() */
  477.     void        *data;
  478.     char        *translations;
  479.     int        nitems;
  480.     PaintMenuItem    *popupMenu;
  481.     Pixmap        icon;
  482. } IconListItem;
  483.  
  484. static Widget        iconListWidget;
  485. static IconListItem    iconList[] = {
  486.     { "brush",    XPMMAP(brush), NULL, BrushOp, 
  487.             "<BtnDown>(2): changeBrush()", MENU(brush), None },
  488.     { "erase",    BITMAP(erase), NULL, EraseOp, 
  489.             "<BtnDown>(2): changeBrush()", MENU(erase), None },
  490.     { "selectBox",    BITMAP(select), NULL, SelectBoxOp, 
  491.             "<BtnDown>(2): changeChroma()", MENU(selectB), None },
  492.     { "selectArea",    BITMAP(selarea), NULL, SelectAreaOp, 
  493.             "<BtnDown>(2): changeChroma()", MENU(selectA), None },
  494.     { "pencil",    XPMMAP(pencil), NULL, PencilOp, 
  495.             NULL, MENU(pencil), None },
  496.     { "dotPencil",    XPMMAP(dotPencil), NULL, DotPencilOp,     
  497.             NULL, MENU(dotPencil), None },
  498.     { "spray",    XPMMAP(spray), NULL, SprayOp, 
  499.             "<BtnDown>(2): changeSpray()", MENU(spray), None },
  500.     { "fill",    XPMMAP(fill), NULL, FillOp, 
  501.             NULL, MENU(fill), None },
  502.     { "text",    BITMAP(text), NULL, FontOp, 
  503.             "<BtnDown>(2): changeFont()", MENU(text), None },
  504.     { "line",    BITMAP(line), NULL, LineOp, 
  505.             NULL, MENU(line), None },
  506.     { "ray",    BITMAP(ray), NULL, RayOp, 
  507.             NULL, MENU(ray), None },
  508.     { "arc",    BITMAP(arc), NULL, ArcOp, 
  509.             NULL, MENU(arc), None },
  510.     { "box",    BITMAP(box), NULL, BoxOp, 
  511.             NULL, MENU(box), None },
  512.     { "fBox",    BITMAP(fbox), NULL, FBoxOp, 
  513.             NULL, MENU(fbox), None },
  514.     { "oval",    BITMAP(oval), NULL, OvalOp, 
  515.             NULL, MENU(oval), None },
  516.     { "fOval",    BITMAP(foval), NULL, FOvalOp, 
  517.             NULL, MENU(foval), None },
  518.     { "cLine",    BITMAP(cline), NULL, CLineOp, 
  519.             NULL, MENU(cline), None },
  520.     { "polygon",    BITMAP(poly), NULL, PolyOp, 
  521.             NULL, MENU(poly), None },
  522.     { "fPolygon",    BITMAP(fpoly), NULL, FPolyOp, 
  523.             NULL, MENU(poly), None },
  524.     { "freehand",    BITMAP(freehand), NULL, FreehandOp, 
  525.             NULL, MENU(freehand), None },
  526.     { "fFreehand",    BITMAP(ffreehand), NULL, FFreehandOp, 
  527.             NULL, MENU(freehand), None },
  528. };
  529.  
  530. void OperationSet(String names[], int num)
  531. {
  532.     IconListItem    *match = NULL;
  533.     int        i, j;
  534.  
  535.     for (i = 0; i < XtNumber(iconList); i++) {
  536.         for (j = 0; j < num; j++) {
  537.             if (strcmp(names[j], iconList[i].name) == 0) {
  538.                 if (match == NULL)
  539.                     match = &iconList[i];
  540.                 if (CurrentOp == iconList[i].data)
  541.                     return;
  542.             }
  543.         }
  544.     }
  545.     if (match != NULL) 
  546.         XawToggleSetCurrent(iconListWidget, (XtPointer)match->name);
  547. }
  548.  
  549. static PaintMenuItem lineMenu[] = {
  550. #if 0
  551.     MI_FLAGCB("0", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  552. #endif
  553.     MI_FLAGCB("1", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  554.     MI_FLAGCB("2", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  555.     MI_FLAGCB("4", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  556.     MI_FLAGCB("6", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  557.     MI_FLAGCB("8", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  558. #define LW_SELECT    5
  559.     MI_FLAGCB("select", MF_CHECK|MF_GROUP1, lineWidth, NULL),
  560. };
  561.  
  562. static PaintMenuItem    fontMenu[] = {
  563.     MI_FLAGCB("Times 8", MF_CHECK|MF_GROUP1,
  564.             fontSet, "-*-times-medium-r-normal-*-*-80-*-*-p-*-*-*"),
  565.     MI_FLAGCB("Times 12", MF_CHECK|MF_GROUP1,
  566.             fontSet, "-*-times-medium-r-normal-*-*-120-*-*-p-*-*-*"),
  567.     MI_FLAGCB("Times 18", MF_CHECK|MF_GROUP1,
  568.             fontSet, "-*-times-medium-r-normal-*-*-180-*-*-p-*-*-*"),
  569.     MI_FLAGCB("Times Bold 12", MF_CHECK|MF_GROUP1,
  570.             fontSet, "-*-times-bold-r-normal-*-*-120-*-*-p-*-*-*"),
  571.     MI_FLAGCB("Times Italic 12", MF_CHECK|MF_GROUP1,
  572.             fontSet, "-*-times-bold-i-normal-*-*-120-*-*-p-*-*-*"),
  573.     MI_FLAGCB("Lucida 12", MF_CHECK|MF_GROUP1,
  574.             fontSet, "-*-lucida-medium-r-normal-*-*-120-*-*-p-*-*-*"),
  575.     MI_FLAGCB("Helvetica 12", MF_CHECK|MF_GROUP1,
  576.             fontSet, "-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*-*"),
  577.     MI_FLAGCB("Helvetica Bold 12", MF_CHECK|MF_GROUP1,
  578.             fontSet, "-*-helvetica-bold-r-normal-*-*-120-*-*-p-*-*-*"),
  579.     MI_FLAGCB("Fixed 12", MF_CHECK|MF_GROUP1,
  580.             fontSet, "-*-fixed-medium-r-normal-*-*-120-*-*-m-*-*-*"),
  581.     MI_FLAGCB("Courier 12", MF_CHECK|MF_GROUP1,
  582.             fontSet, "-*-courier-medium-r-normal-*-*-120-*-*-m-*-*-*"),
  583.     MI_SEPERATOR(),
  584. #define FM_SELECT    11
  585.     MI_FLAGCB("select", MF_CHECK|MF_GROUP1, fontSet, NULL),
  586. };
  587.  
  588. static PaintMenuItem otherMenu[] = {
  589.     MI_SIMPLECB("brushSelect", BrushSelect, NULL),
  590. #define SP_SELECT    1
  591.     MI_SIMPLECB("sprayEdit", sprayMenuCallback, NULL),
  592. };
  593.  
  594. static PaintMenuItem fileMenu[] = {
  595.     MI_SIMPLECB("new",       GraphicCreate, 0),
  596.     MI_SIMPLECB("new-size",  GraphicCreate, 2),
  597.     MI_SIMPLECB("open",      GraphicCreate, 1),
  598.     MI_SIMPLECB("load-clip", loadClipboard, NULL),
  599.     MI_SEPERATOR(),
  600.     MI_SIMPLECB("quit", exitPaint, NULL),
  601. };
  602.  
  603. static PaintMenuItem helpMenu[] = {
  604.     MI_SIMPLECB("about", HelpDialog, "about"),
  605.     MI_SEPERATOR(),
  606.     MI_SIMPLECB("help", HelpDialog, "toolbox.toolbox"),
  607. };
  608.  
  609. static PaintMenuBar   menuBar[] = {
  610.     { None, "file",  XtNumber(fileMenu), fileMenu },
  611. #if 0
  612.     { None, "other",  XtNumber(otherMenu), otherMenu },
  613. #endif
  614.     { None, "line",  XtNumber(lineMenu), lineMenu },
  615.     { None, "font",  XtNumber(fontMenu), fontMenu },
  616.     { None, "help",  XtNumber(helpMenu), helpMenu },
  617. };
  618. /*
  619. **  Now for the callback functions
  620. */
  621.  
  622. static int    argListLen = 0;
  623. static Arg    *argList;
  624.  
  625. void OperationSetPaint(Widget paint)
  626. {
  627.     XtSetValues(paint, argList, argListLen);
  628. }
  629.  
  630. void OperationAddArg(Arg arg)
  631. {
  632.     int    i;
  633.  
  634.     for (i = 0; i < argListLen; i++) {
  635.         if (strcmp(argList[i].name, arg.name) == 0) {
  636.             argList[i].value = arg.value;
  637.             return;
  638.         }
  639.     }
  640.  
  641.     if (argListLen == 0)
  642.         argList = (Arg *)XtMalloc(sizeof(Arg) * 2);
  643.     else
  644.         argList = (Arg *)XtRealloc((XtPointer)argList, sizeof(Arg) * (argListLen + 2));
  645.  
  646.     argList[argListLen++] = arg;
  647. }
  648.  
  649. /*
  650. **  Double click action callback functions.
  651. */
  652. static void changeLineAction(Widget w, XEvent *event)
  653. {
  654.     lineWidth(lineMenu[LW_SELECT].widget, (int)lineMenu[LW_SELECT].data);
  655. }
  656. static void changeSprayAction(Widget w, XEvent *event)
  657. {
  658.     sprayMenuCallback(w);
  659. }
  660. static void changeBrushAction(Widget w, XEvent *event)
  661. {
  662.     BrushSelect(w);
  663. }
  664. static void changeChromaAction(Widget w, XEvent *event)
  665. {
  666.     SelectChromaDialog(w);
  667. }
  668. static void changeFontAction(Widget w, XEvent *event)
  669. {
  670.     fontSet(fontMenu[FM_SELECT].widget, (char *)fontMenu[FM_SELECT].data);
  671. }
  672.     
  673. /*
  674. **  The real init function
  675. */
  676. void OperationInit(Widget toplevel)
  677. {
  678.     static XtActionsRec    acts[] = {
  679.                     { "changeLine", (XtActionProc)changeLineAction },
  680.                     { "changeBrush", (XtActionProc)changeBrushAction },
  681.                     { "changeFont", (XtActionProc)changeFontAction },
  682.                     { "changeSpray", (XtActionProc)changeSprayAction },
  683.                     { "changeChroma", (XtActionProc)changeChromaAction },
  684.                 };
  685.     int        i;
  686.     Pixmap        pix;
  687.     Widget        vport, form, box, icon, bar, firstIcon = None;
  688.     Pixel        fg, bg;
  689.     char        *defTrans = "<BtnDown>,<BtnUp>: set() notify()\n";
  690.     XtTranslations    trans = XtParseTranslationTable(defTrans);
  691.     IconListItem    *cur;
  692.  
  693.     form = XtVaCreateManagedWidget("toolbox", 
  694.             formWidgetClass, toplevel,
  695.             XtNborderWidth, 0,
  696.             NULL);
  697.     XtAppAddActions(XtWidgetToApplicationContext(toplevel), acts, XtNumber(acts));
  698.     /*
  699.     **  Create the menu bar
  700.     */
  701.     bar = MenuBarCreate(form, XtNumber(menuBar), menuBar);
  702.  
  703.     /*
  704.     **  Create the operation icon list
  705.     */
  706.     vport = XtVaCreateManagedWidget("vport", 
  707.             viewportWidgetClass, form,
  708.             XtNallowVert, True,
  709.             XtNuseRight, True,
  710.             XtNfromVert, bar,
  711.             NULL);
  712.     box = XtVaCreateManagedWidget("box", 
  713.             boxWidgetClass, vport,
  714.             XtNwidth, 32 * 8,
  715.             XtNtop, XtChainTop,
  716.             NULL);
  717.  
  718.     for (i = 0; i < XtNumber(iconList); i++) {
  719.         cur = &iconList[i];
  720.  
  721.         icon = XtVaCreateManagedWidget(cur->name,
  722.             toggleWidgetClass, box,
  723.             XtNtranslations, trans,
  724.             XtNradioGroup, firstIcon,
  725.             XtNradioData, cur->name,
  726.             NULL);
  727.  
  728.         if (cur->bitmap != NULL) {
  729.             XtVaGetValues(icon, XtNforeground, &fg,
  730.                         XtNbackground, &bg, 
  731.                         NULL);
  732.  
  733.             bg = WhitePixelOfScreen(XtScreen(box));
  734.             fg = BlackPixelOfScreen(XtScreen(box));
  735.  
  736.             pix = XCreatePixmapFromBitmapData(
  737.                     XtDisplay(box), 
  738.                     DefaultRootWindow(XtDisplay(box)),
  739.                     cur->bitmap,
  740.                     cur->width,
  741.                     cur->height,
  742.                     fg, bg,
  743.                     DefaultDepthOfScreen(XtScreen(box)));
  744.  
  745.         } else if (cur->xpmmap != NULL) {
  746.             XpmCreatePixmapFromData(
  747.                     XtDisplay(box), 
  748.                     DefaultRootWindow(XtDisplay(box)),
  749.                     cur->xpmmap,
  750.                     &pix, NULL, NULL);
  751.         } else {
  752.             pix = None;
  753.         }
  754.  
  755.         cur->icon = pix;
  756.  
  757.         if (pix != None)
  758.             XtVaSetValues(icon, XtNbitmap, pix, NULL);
  759.         if (cur->translations != NULL) {
  760.             XtTranslations moreTrans;
  761.  
  762.             moreTrans = XtParseTranslationTable(cur->translations);
  763.             XtAugmentTranslations(icon, moreTrans);
  764.         }
  765.  
  766.         if (firstIcon == NULL) {
  767.             XtVaSetValues(icon, XtNstate, True, NULL);
  768.             setOperation(icon, cur->data, NULL);
  769.  
  770.             firstIcon = icon;
  771.             iconListWidget = icon;
  772.         }
  773.         if (cur->callback != NULL)
  774.             XtAddCallback(icon, XtNcallback, 
  775.                 cur->callback, cur->data);
  776.         else
  777.             XtAddCallback(icon, XtNcallback, 
  778.                 setOperation, cur->data);
  779.  
  780. #if 1
  781.         if (cur->nitems != 0 && cur->popupMenu != NULL)
  782.             MenuPopupCreate(icon, cur->nitems, cur->popupMenu);
  783. #endif
  784.     }
  785.  
  786.     lineWidth(lineMenu[0].widget, (int)lineMenu[0].data);
  787.     fontSet(fontMenu[1].widget, fontMenu[1].data);
  788.  
  789.     AddDestroyCallback(toplevel, 
  790.         (void (*)(Widget, void *, XEvent *))exitPaint, NULL);
  791. }
  792.  
  793. Image *OperationIconImage(Widget w, char *name)
  794. {
  795.     Image    *img;
  796.     int    i;
  797.  
  798.     for (i = 0; i < XtNumber(iconList); i++) 
  799.         if (strcmp(name, iconList[i].name) == 0)
  800.             break;
  801.     if (i == XtNumber(iconList) || iconList[i].icon == None)
  802.         return NULL;
  803.  
  804.     return PixmapToImage(w, iconList[i].icon, None);
  805. }
  806.